package top.goldenyear.porpoise.dev.code.util;

import cn.hutool.v7.core.collection.CollUtil;
import top.goldenyear.porpoise.dev.code.model.CodeColumn;
import top.goldenyear.porpoise.dev.code.model.CodeTable;
import top.goldenyear.porpoise.framework.web.core.generator.IMetaBuilder;
import top.goldenyear.porpoise.framework.web.core.generator.config.DomainConfig;
import top.goldenyear.porpoise.framework.web.core.generator.config.GlobalConfig;
import top.goldenyear.porpoise.framework.web.core.generator.config.StrategyConfig;
import top.goldenyear.porpoise.framework.web.core.generator.model.ColumnMeta;
import top.goldenyear.porpoise.framework.web.core.generator.model.TableMeta;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author airhead
 */
public class CodeGenMetaBuilder implements IMetaBuilder {
  private final CodeTable codeTable;
  private final List<CodeColumn> codeColumns;
  private final List<CodeTable> subCodeTables;
  private final Map<Integer, List<CodeColumn>> subCodeColumns;
  private final GlobalConfig globalConfig;

  public CodeGenMetaBuilder(
      GlobalConfig globalConfig,
      CodeTable codeTable,
      List<CodeColumn> codeColumns,
      List<CodeTable> subCodeTables,
      Map<Integer, List<CodeColumn>> subCodeColumns) {
    this.globalConfig = globalConfig;
    this.codeTable = codeTable;
    this.codeColumns = codeColumns;
    this.subCodeTables = subCodeTables;
    this.subCodeColumns = subCodeColumns;
  }

  @Override
  public List<TableMeta> buildTables() {
    buildConfig();

    List<TableMeta> tableMetas = new ArrayList<>();
    TableMeta tableMeta = CodeGenUtils.buildTableMeta(codeTable);
    List<ColumnMeta> columnMetas = CodeGenUtils.buildColumnMeta(codeColumns);
    tableMeta.setColumnMetas(columnMetas);
    tableMetas.add(tableMeta);

    if (CollUtil.isEmpty(subCodeTables)) {
      return tableMetas;
    }

    for (CodeTable subCodeTable : subCodeTables) {
      TableMeta subTableMeta = CodeGenUtils.buildTableMeta(subCodeTable);
      List<CodeColumn> subCodeColumns = this.subCodeColumns.get(subCodeTable.getId());
      List<ColumnMeta> subCodeColumnMetas = CodeGenUtils.buildColumnMeta(subCodeColumns);
      subTableMeta.setColumnMetas(subCodeColumnMetas);

      tableMetas.add(subTableMeta);
    }

    return tableMetas;
  }

  private void buildConfig() {
    globalConfig.setBasePackage(codeTable.getBasePackage());
    globalConfig.setSourceDir(codeTable.getSourceDir());
    globalConfig.setUiSourceDir(codeTable.getUiSourceDir());

    StrategyConfig strategyConfig = globalConfig.getStrategyConfig();
    strategyConfig.setOnlyGenAssignTable(true);
    List<String> tableNames = new ArrayList<>();
    tableNames.add(codeTable.getName());
    if (CollUtil.isNotEmpty(subCodeTables)) {
      for (CodeTable subCodeTable : subCodeTables) {
        tableNames.add(subCodeTable.getName());
      }
    }
    strategyConfig.addDomainConfig(
        DomainConfig.of()
            .setTablePrefix(codeTable.getTablePrefix())
            .setBiz(codeTable.getBiz())
            .setDomain(codeTable.getDomain())
            .addTable(tableNames.toArray(new String[0])));

    strategyConfig.addTableConfig(CodeGenUtils.buildTableConfig(codeTable));
    if (CollUtil.isNotEmpty(subCodeTables)) {
      for (CodeTable subCodeTable : subCodeTables) {
        strategyConfig.addTableConfig(CodeGenUtils.buildTableConfig(subCodeTable));
      }
    }

    for (CodeColumn codeColumn : codeColumns) {
      strategyConfig.addColumnConfig(CodeGenUtils.buildColumnConfig(codeTable, codeColumn));
    }

    if (CollUtil.isNotEmpty(subCodeTables)) {
      for (CodeTable subCodeTable : subCodeTables) {
        List<CodeColumn> subTableCodeColumns = this.subCodeColumns.get(subCodeTable.getId());
        if (CollUtil.isNotEmpty(subTableCodeColumns)) {
          continue;
        }

        for (CodeColumn codeColumn : subTableCodeColumns) {
          strategyConfig.addColumnConfig(CodeGenUtils.buildColumnConfig(subCodeTable, codeColumn));
        }
      }
    }
  }
}
